import json
import re
from django import http
from django.contrib.auth import authenticate, login, logout
from django.shortcuts import render
from django.views import View
from django_redis import get_redis_connection

from users.models import User

from ihome_01.settings.dev import QINIUYUN_URL
from ihome_01.utils.my_file_type import image_file
from ihome_01.utils.response import RET
from ihome_01.utils.my_loginview import LoginRequiredView
from ihome_01.libs.qiniuyun.qiniu_storage import storage


# 用户注册
class UserRegisterView(View):
    # 用户注册
    def post(self, request):
        # 1. 获取参数
        data_dict = json.loads(request.body.decode())
        mobile = data_dict.get("mobile")
        phonecode = data_dict.get("phonecode")
        password = data_dict.get("password")

        # 2.校验参数
        # 2.1 为空检验
        if not all([mobile,phonecode,password]):
            return http.JsonResponse({"errno": RET.NECESSARYPARAMERR,"errmsg": "参数不全"})

        # 2,2 手机号格式
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.JsonResponse({"errno": RET.MOBILEERR, "errmsg": "手机号格式有误"})

        # 2.3 短信验证码正确
        redis_conn = get_redis_connection("code")
        sms_code = redis_conn.get("sms_code_%s" % mobile)
        if phonecode != sms_code.decode():
            return http.JsonResponse({"errno": RET.SMSCODERR,"errmsg": "短信验证码错误"})

        # 2.4 手机号重复检测
        count = User.objects.filter(mobile=mobile).count()
        if count != 0:
            return http.JsonResponse({"erron": RET.DATAEXIST,"errmsg": "该手机号已注册"})

        # 2.5 密码长度检验
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return http.JsonResponse({"erron": RET.PWDERR,"errmsg": "密码最少8位，最长20位"})

        # 3, 数据入库
        user = User()
        user.username=mobile
        user.password=password
        user.mobile=mobile
        try:
            user.save()
        except Exception as e:
            return http.JsonResponse({"errno": RET.DBERR, "errmsg": "数据库保存失败"})

        # 4. 返回响应
        response = http.JsonResponse({"errno": RET.OK, "errmsg": "注册成功"})
        response.set_cookie("username", user.mobile)
        return response


# 用户登陆与退出
class UserSessionView(View):
    # 用户登陆--登陆界面
    def post(self,request):
        # 1. 获取参数
        data_dict = json.loads(request.body.decode())
        mobile = data_dict.get("mobile")
        password = data_dict.get("password")

        # 2. 校验参数
        # 2.1 为空校验
        if not all([mobile,password]):
            return http.JsonResponse({"errno": RET.NECESSARYPARAMERR, "errmsg": "参数不全"})

        #2,2 账号密码正确性校验, 如果认证成功返回用户对象, 不成功返回None
        user = authenticate(request, username=mobile, password=password)
        if not user:
            return http.JsonResponse({"errno": RET.DATAERR, "errmsg": "账号或者密码不正确"})

        # 3. 状态保持
        login(request, user) # 就是将用户的信息存储在session
        request.session.set_expiry(3600*24*2)  #两天

        # 4,返回响应
        response = http.JsonResponse({"errno": RET.OK, "errmsg": "登录成功"})
        response.set_cookie("username", user.mobile)
        return response

    # 用户判断登陆
    def get(self,request):
        # 1. 获取参数
        cookie_mobile = request.COOKIES.get("username")
        try:
            user = User.objects.get(mobile=cookie_mobile)
        except Exception as e:
            return http.JsonResponse({"errno": RET.DBERR, "errmsg": "已登录"})

        # 2. 数据拼接，返回响应
        data = {"name":user.username,
                "user_id":user.id
                }
        if cookie_mobile:
            response = {"errno": RET.OK, "errmsg": "已登录", "data": data}
            return http.JsonResponse(response)
        else:
            response = {"errno": RET.SESSIONERR, "errmsg": "未登录"}
            return http.HttpResponse(response)

    # 用户退出登陆
    def delete(self,request):
        # 清理session
        logout(request)
        response = http.JsonResponse({"errno": RET.OK, "errmsg":"已登出"})

        # 退出登录时清除cookie中的username
        response.delete_cookie('username')
        return response


# 个人中心
class UserInfoView(LoginRequiredView):
    def get(self,request):
        # 1. 获取参数
        cookie_mobile = request.COOKIES.get("username")
        user = User.objects.get(mobile=cookie_mobile)

        if user.avatar:
            # 2. 拼接数据
            data = {"name": user.username,
                    "mobile": user.mobile,
                    "user_id": user.id,
                    "avatar_url":QINIUYUN_URL + user.avatar.url,
                    }
        else:
            # 2. 拼接数据
            data = {"name": user.username,
                    "mobile": user.mobile,
                    "user_id": user.id,
                    "avatar_url": None,
                    }
        return http.JsonResponse({"errno": RET.OK,"errmsg": "OK", "data":data})


# 修改头像
class UserAvatarView(LoginRequiredView):
    def post(self,request):
        # 1. 获取参数
        avatar = request.FILES.get("avatar")

        # 2. 校验参数
        # 2.1 为空校验
        if not avatar:
            return http.JsonResponse({"errno": RET.PARAMERR,"errmsg": "参数错误"})

        if not image_file(avatar):
            return http.JsonResponse({"errno": RET.PARAMERR,"errmsg": "图片格式错误"})

        # 读取出文件对象的二进制数据
        file_data = avatar.read()

        # 将图片上传到千牛云
        try:
            key = storage(file_data)
        except Exception as e:
            return http.JsonResponse({"errno": RET.THIRDERR, "errmsg": "上传图片失败"})

        # 将千牛云上传的图片地址保存到数据库
        cookie_mobile = request.COOKIES.get("username")
        user = User.objects.get(mobile=cookie_mobile)
        try:
            User.objects.filter(mobile=cookie_mobile).update(avatar=key)
        except Exception as e:
            return http.JsonResponse({"errno": RET.DBERR, "errmsg": "上传数据库失败"})

        # 3. 拼接数据，返回响应
        data = {"user_id": user.id,
                "avatar_url":QINIUYUN_URL + user.avatar.url,
                }
        return http.JsonResponse({"errno": RET.OK, "errmsg": "图片上传成功","data":data})


# 修改用户名
class UserNameView(LoginRequiredView):
    def put(self,request):
        # 1. 获取参数
        data_dict = json.loads(request.body.decode())
        name = data_dict.get("name")
        cookie_mobile = request.COOKIES.get("username")

        # 2, 数据校验
        # 2.1 为空校验
        if not all([name]):
            return http.JsonResponse({"errno": RET.NECESSARYPARAMERR, "errmsg": "参数不全"})

        # 3, 数据入库
        try:
            User.objects.filter(mobile=cookie_mobile).update(username=name)
        except Exception as e:
            return http.JsonResponse({"errno": RET.DBERR, "errmsg": "修改失败"})

        return http.JsonResponse({"errno": RET.OK, "errmsg": "修改成功"})


# 实名认证
class UserAuthView(LoginRequiredView):
    def get(self,request):
        cookie_mobile = request.COOKIES.get("username")
        user = User.objects.get(mobile=cookie_mobile)
        # 2. 拼接数据
        data = {"real_name": user.real_name,
                "id_card": user.id_card,
                "user_id": user.id,
                }
        return http.JsonResponse({"errno": RET.OK,"errmsg": "OK", "data":data})

    def post(self,request):
        # 1. 获取参数
        cookie_mobile = request.COOKIES.get("username")
        data_dict = json.loads(request.body.decode())
        real_name = data_dict.get("real_name")
        id_card = data_dict.get("id_card")
        user = User.objects.get(mobile=cookie_mobile)
        # 2. 校验参数
        # 2.1 为空校验
        if not all([real_name,id_card]):
            return http.JsonResponse({"errno": RET.NECESSARYPARAMERR, "errmsg": "参数不全"})
        # 2.2 身份证号码校验
        if not re.match(r'^[1-9]\d{5}(18|19|20|(3\d))\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$', id_card):
            return http.JsonResponse({"erron": RET.DATAERR,"errmsg": "身份证号码错误"})
        # 3, 数据入库
        try:
            User.objects.filter(mobile=cookie_mobile).update(real_name=real_name, id_card=id_card)
        except Exception as e:
            return http.JsonResponse({"errno": RET.DBERR, "errmsg": "数据库保存失败"})
        # 4. 拼接数据，返回响应
        data = {"real_name": user.real_name,
                "id_card": user.id_card,
                "user_id": user.id,
                }
        return http.JsonResponse({"errno": RET.OK, "errmsg": "认证信息保存成功", "data": data})
